from __future__ import absolute_import
import json
from datetime import datetime, timedelta
from urllib import parse
import requests
from requests.cookies import cookiejar_from_dict

# event格式参考
'''
{
    'Records': [
        {
            'eventVersion': '2.0',
            'eventSource': 'aws:s3',
            'awsRegion': 'cn-south-1',
            'eventTime': '2021-12-25T08:02:30.389Z',
            'eventName': 'ObjectCreated:Put',
            'userIdentity': {'principalId': '879c657349c44a9c9ac345867ea999d1'},
            'requestParameters': {'sourceIPAddress': '10.48.51.83'},
            'responseElements': {'x-amz-request-id': '35a9e0041b7a4bff8903365011f81fe2',
                              'x-amz-id-2': 'FJZA3Hq0hNm8ZQAECeAjlglzI4iBNSG/Y347hRAIjtlzR4AnHjs/JfEy1+bOi8tE'},
            's3': {
                's3SchemaVersion': '1.0',
                'configurationId': 'obs-event-18t4',
                'bucket': {
                    'name': 'autopolit',
                    'ownerIdentity': {
                        'PrincipalId': '8c1d78bc75bf4154a4d0c73a28c3e0b5'
                    },
                    'arn': 'arn:aws:s3:::autopolit'
                },
                'object': {
                    'key': 'setup.py', #'dir1%2F__init__.py'
                    'eTag': 'a6e683a165f9443a3224a010923cd240',
                    'size': 1149,
                    'versionId': 'null',
                    'sequencer': '0000000017DF09CD77FD0596C0000000'
                }
            }
         }
    ]
}
'''
logger = None


class S3Object:
    def __init__(self, event):
        self.region = ""
        self.collect_time = ""
        self.bucket_name = ""
        self.object_name = ""
        self.size = ""
        self.path = None
        self.file_name = None
        self.status = False
        self.error_msg = ""
        self.get_value_from_event(event=event)

    def get_value_from_event(self, event):
        try:
            self.region = event['Records'][0]['awsRegion']
            self.collect_time = event['Records'][0]['eventTime']
            # Obtains a bucket name.
            # Obtains the name of an uploaded object.
            if 's3' in event['Records'][0]:
                s3 = event['Records'][0]['s3']
                self.bucket_name = parse.unquote(s3['bucket']["name"])
                self.object_name = parse.unquote(s3['object']["key"])
            else:
                obs_info = event['Records'][0]['obs']
                self.bucket_name = parse.unquote(obs_info['bucket']["name"])
                self.object_name = parse.unquote(obs_info['object']["key"])
            self.size = int(event['Records'][0]['s3']['object']["size"])
            self.path = "obs://{}/{}".format(self.bucket_name, self.object_name)
            self.file_name = self.object_name.split("/")[-1]
            self.status = True
        except Exception as e:
            global logger
            logger.error("invalid event, {}".format(str(e)))
            self.error_msg = str(e)
            self.status = False


class APIClient:
    def __init__(self):
        self.error_msg = ""
        self.ploto_username = None
        self.ploto_password = None
        self.api_ploto_login = None
        self.api_ploto_anonymized_add = None
        self.topic_urn = None
        self.topic_region = None

        self.s3_object = None

    def get_values(self, event, context):
        context_status = True  # 用来判断配置正确性
        error_msg = ""
        self.ploto_username = context.getUserData('plotoUsername')
        self.ploto_password = context.getUserData('plotoPassword')
        if self.ploto_username is None or self.ploto_password is None:
            context_status = False
            error_msg = "{}{}\n".format(error_msg,
                                        "invalid context, not got ploto user information(plotoUsername/plotoPassword)")

        self.api_ploto_login = context.getUserData('apiPlotoLogin')
        self.api_ploto_anonymized_add = context.getUserData('apiPlotoAdd')
        if self.api_ploto_login is None or self.api_ploto_anonymized_add is None:
            context_status = False
            error_msg = "{}{}\n".format(error_msg,
                                        "invalid context, not got ploto api information(apiPlotoLogin/apiPlotoAdd)")
        self.topic_urn = context.getUserData('topicUrn')  # 消息通知的主题，可从官网console页面查找
        if self.topic_urn is not None:
            topic_split = self.topic_urn.split(":")
            if len(topic_split) != 5:
                context_status = False
                error_msg = "{}{}\n".format(error_msg, "invalid context, Parameter: topicUrn.")
            self.topic_region = topic_split[2]

        self.s3_object = S3Object(event)
        if not self.s3_object.status:
            context_status = False
            error_msg = "{}{}\n".format(error_msg, "invalid event, {}".format(self.s3_object.error_msg))

        self.error_msg = error_msg
        return context_status


def handler(event, context):
    global logger
    logger = context.getLogger()
    api_client = APIClient()
    if not api_client.get_values(event, context):
        raise Exception(api_client.error_msg)

    if api_client.s3_object.size == 0:
        # size = 0 表示该对象为目录，无需进行后续操作
        logger.warning("invalid object, size was 0.")
        return "OK"

    headers = {"Content-Type": "application/json"}
    data = {"username": api_client.ploto_username, "password": api_client.ploto_password}
    session = requests.Session()
    session.post(url=api_client.api_ploto_login, data=json.dumps(data), headers=headers)
    request_cookies = session.cookies.get_dict()
    token = request_cookies["csrftoken"]
    session_id = request_cookies["sessionid"]
    cookie_dict = dict()
    cookie_dict["sessionid"] = session_id
    cookie_dict["csrftoken"] = token
    cookies = cookiejar_from_dict(cookie_dict=cookie_dict)

    headers = {"Content-Type": "application/json", "X-CSRFToken": token, "sessionid": session_id}
    obj = api_client.s3_object
    data = []
    collect_time = datetime.strptime(obj.collect_time, "%Y-%m-%dT%H:%M:%S.%fZ")
    local_time = collect_time + timedelta(hours=8)
    res_time = local_time.strftime("%Y-%m-%d %H:%M:%S")
    data_obj = {"name": obj.file_name, "size": obj.size, "storage_type": 0, "restoration_status": 0,
                "collect_time": res_time, "region": obj.region, "url": obj.path,
                "bucket_name": obj.bucket_name, "object_key": obj.object_name}
    data.append(data_obj)
    request_param = dict()
    request_param['data'] = data
    requests.post(url=api_client.api_ploto_anonymized_add, data=json.dumps(request_param),
                  headers=headers, cookies=cookies)
    return "OK"
